import {getToken, setToken} from "@/service/TokenUtils"
import {getMathRand} from "@/utils/index.js"
import ServiceConfig from "@/service/ServiceConfig"
import axios from "axios"
import {Message} from "element-ui"
import {startLoading, endLoading} from "@/utils/VueLoad"
import EncryptUtil from "@/utils/encrypt"

export default class BaseService {
	constructor() {
		this.serviceConfig = ServiceConfig.getInstance()
		this.initAxiosConfig()
	}

	getBaseUrl() {
		console.error("初始化模块路径必须实现BaseUrl!")
	}

	initAxiosConfig() {
		// 超时时间
		axios.defaults.timeout = 60000
		// 跨域请求，允许保存cookie
		//axios.defaults.withCredentials = true
		axios.defaults.headers = {
			"Content-Type": "application/json; charset=utf-8",
		}
	}

	/**
	 * 描述:post请求
	 * @param url
	 * @param parameter
	 * @param config
	 * @returns {AxiosPromise}
	 */
	postAction(url, parameter = {}, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			data: JSON.stringify(parameter),
			...config,
		})
	}

	/**
	 * 描述:post请求
	 * @param url
	 * @param parameter
	 * @param config
	 * @returns {AxiosPromise}
	 */
	postEncryAction(url, parameter = {}, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			data: JSON.stringify(parameter),
			encry: true,
			...config,
		})
	}

	/**
	 * 描述:post请求--url拼接参数
	 * @param url
	 * @param parameter
	 * @param config
	 * @returns {AxiosPromise}
	 */
	postUrlAction(url, parameter = {}, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			params: parameter,
			...config,
		})
	}

	/**
	 * 描述:get请求
	 * @param url
	 * @param parameter
	 * @param config
	 * @returns {AxiosPromise}
	 */
	getAction(url, parameter = {}, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "get",
			params: parameter,
			...config,
		})
	}
	/**
	 * 描述:get请求
	 * @param url
	 * @param parameter
	 * @param config
	 * @returns {AxiosPromise}
	 */
	getServer(server, path, parameter = {}, config = {}) {
		return axios({
			baseURL: server,
			url: path,
			method: "get",
			params: parameter,
			...config,
		})
	}

	postUploadFile(url, form, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			data: form,
			...config,
		})
	}

	postUploadFile(url, form, fn, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			data: form,
			onUploadProgress: fn,
			...config,
		})
	}

	postDownloadFile(url, form, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "post",
			responseType: "blob",
			data: form,
			...config,
		})
	}

	getDownloadction(url, parameter = {}, config = {}) {
		return axios({
			baseURL: this.getBaseUrl(),
			url: url,
			method: "get",
			responseType: "blob",
			params: parameter,
			...config,
		})
	}

	/**
	 * 描述:去登陆信息
	 */
	goLogin() {
		location.href = this.serviceConfig.getLoginUrl()
	}

	/**
	 * 描述:初始化拦截
	 */
	static initInterceptors() {
		const encryptUtil = new EncryptUtil()
		axios.interceptors.request.use(
			config => {
				if (!config.hasOwnProperty("loading") || config.loading) {
					startLoading()
				}
				const token = getToken()
				if (token) {
					// 请求头带上token
					config.headers["token"] = getToken()
				}
				if (config.method === "post" && config.data && config.encry) {
					if (typeof config.data === "string") {
						let encrynum = getMathRand(6)
						config.headers["encry"] = encrynum
						config.data = encryptUtil.encrypt(encrynum, config.data)
					} else {
						console.log("payload 不为字符串， config, ", config)
					}
				}
				return config
			},
			error => {
				endLoading()
				return Promise.reject(error)
			},
		)

		/**
		 * 响应拦截
		 */
		axios.interceptors.response.use(
			response => {
				if (!response.config.hasOwnProperty("loading") || response.config.loading) {
					endLoading()
				}
				if (response.data && response.data.code === 401) {
					// 401, token失效
					this.goLogin()
				}
				let encrynum = response.headers.encry
				if (encrynum) {
					let decryptData = encryptUtil.decrypt(encrynum, response.data)
					response.data = JSON.parse(decryptData)
				}
				if (!(response.status === 200 || response.data.code === 0)) {
					Message({
						message: "提交失败",
						type: "error",
						showClose: true,
						dangerouslyUseHTMLString: true,
						duration: 3000,
					})
				}
				// 每次请求都设置新的token
				if (response.headers["token"]) {
					setToken(response.headers["token"])
				}
				return response
			},
			error => {
				endLoading()
				Message({
					message: "网络异常，请稍后重试",
					type: "error",
					showClose: true,
					duration: 3000,
				})
				return Promise.reject(error)
			},
		)
	}
}
BaseService.initInterceptors()
